using System;
using System.Collections;
using System.Text;
using System.Xml;

namespace Slaks.DocumentSerialization.Document.Wordnet
{
	public class WordnetDocument2Xml
	{
		public static void WriteXml(WordnetDocument doc, string filename, Encoding encoding)
		{
			XmlTextWriter writer = null;

			try
			{
				writer = new XmlTextWriter(filename, encoding);
				writer.Formatting = Formatting.Indented;
				writer.WriteStartDocument();

				writer.WriteStartElement(Grammar.WordnetDocument.WordnetDocumentElement);
				writer.WriteElementString(Grammar.Document.FileNameElement, doc.FileName);
				writer.WriteElementString(Grammar.Document.TotalTermCountElement, doc.TotalTermCount.ToString());
				writer.WriteElementString(Grammar.Document.UniqueTermCountElement, doc.UniqueTermCount.ToString());
				writer.WriteElementString(Grammar.Document.TotalSentenceCountElement, doc.TotalSentenceCount.ToString());

				WriteMostFrequencyInfo(writer, doc.MostFrequencyInfo);
				WriteNodes(writer, doc.Nodes);

				writer.WriteEndElement();

				writer.WriteEndDocument();
			}
			catch (Exception ex)
			{
				throw ex;
			}
			finally
			{
				writer.Close();
			}
		}

		private static void WriteMostFrequencyInfo(XmlTextWriter writer, MostFrequencyInfo mostFrequencyInfo)
		{
			writer.WriteStartElement(Grammar.MostFrequencyInfo.MostFreqyencyInfoElement);
			long id;

			writer.WriteElementString(Grammar.MostFrequencyInfo.TotalMostFrequentIdElement, mostFrequencyInfo.TotalMostFrequentId.ToString());
			foreach (string sectionName in mostFrequencyInfo.SectionType2IdMap.Keys)
			{
				id = mostFrequencyInfo.SectionType2IdMap[sectionName];

				writer.WriteStartElement(Grammar.MostFrequencyInfo.SectionFrequencyElement);
				writer.WriteAttributeString(Grammar.MostFrequencyInfo.SectionFrequencyNameAttribute, sectionName);
				writer.WriteAttributeString(Grammar.MostFrequencyInfo.SectionFrequencyIdAttribute, id.ToString());
				writer.WriteEndElement();
			}
			writer.WriteEndElement();
		}

		private static void WriteNodes(XmlTextWriter writer, ICollection nodes)
		{
			IEnumerator nodeEnum = nodes.GetEnumerator();
			while (nodeEnum.MoveNext())
			{
				WordnetNode node = (WordnetNode) nodeEnum.Current;
				writer.WriteStartElement(Grammar.Node.NodeElement);
					
				  
				writer.WriteElementString(Grammar.Node.IdElement, node.Id.ToString());
				writer.WriteElementString(Grammar.Node.TermElement, node.Term);
				writer.WriteElementString(Grammar.Node.TotalTermFrequencyElement, node.TotalTermFrequency.ToString());

				WriteSenses(writer,node);

				WriteSections(writer, node.Sections);
				writer.WriteEndElement();
			}
		}

		private static void WriteSenses(XmlTextWriter writer,WordnetNode node)
		{
			
			writer.WriteStartElement(Grammar.Senses.SensesElement);
				writer.WriteElementString(Grammar.Senses.TotalElement,node.SenseInfo.GetTotalSenses().ToString());
				writer.WriteElementString(Grammar.Senses.NounElement,node.SenseInfo.Nouns.ToString());
				writer.WriteElementString(Grammar.Senses.VerbElement,node.SenseInfo.Verbs.ToString());
				writer.WriteElementString(Grammar.Senses.AdjectiveElement,node.SenseInfo.Adjectives.ToString());
				writer.WriteElementString(Grammar.Senses.AdverbElement,node.SenseInfo.Adverbs.ToString());
			  
			  WriteSynonymList(writer,node.SynonymList);
			writer.WriteEndElement();
		}

		private static void WriteSynonymList(XmlTextWriter writer,IList synonymList)
		{
			if (synonymList.Count <= 0) return;
			foreach(Synonym synonym in synonymList)
			{
				WriteSynonymIds(writer,synonym);
			}
		}
		private static void WriteSynonymIds(XmlTextWriter writer,Synonym synonym)
		{
			writer.WriteStartElement(Grammar.Synonym.SynonymElement);
		  foreach(long id in synonym.SynonymIdList())
		  {
		  	writer.WriteElementString(Grammar.Synonym.SynonymIdElement,id.ToString());
		  }
			writer.WriteEndElement();
		}

		private static void WriteSections(XmlTextWriter writer, ICollection sections)
		{
			IEnumerator sectionEnum = sections.GetEnumerator();
			while (sectionEnum.MoveNext())
			{
				Section section = (Section) sectionEnum.Current;

				writer.WriteStartElement(Grammar.Section.SectionElement);
				writer.WriteAttributeString(Grammar.SectionType.SectionTypeAttribute, GetSectionTypeAttribute(section.Type));
				writer.WriteElementString(Grammar.Section.TermFrequencyElement, section.TermFrequency.ToString());
				WriteSentences(writer, section.Sentences);
				writer.WriteEndElement();
			}
		}

		private static string GetSectionTypeAttribute(Section.SectionType sectionType)
		{
			switch (sectionType)
			{
				case Section.SectionType.Heading:
					return Grammar.SectionType.HeadingTypeAttribute;
				case Section.SectionType.Title:
					return Grammar.SectionType.TitleTypeAttribute;
				case Section.SectionType.Caption:
					return Grammar.SectionType.CaptionTypeAttribute;
				case Section.SectionType.Text:
					return Grammar.SectionType.TextTypeAttribute;
				case Section.SectionType.Link:
					return Grammar.SectionType.LinkTypeAttribute;
				case Section.SectionType.MetaDescription:
					return Grammar.SectionType.MetaDescriptionTypeAttribute;
				case Section.SectionType.MetaKeyword:
					return Grammar.SectionType.MataKeywordTypeAttribute;
			}
			return "";
		}

		private static void WriteSentences(XmlTextWriter writer, ICollection sentences)
		{
			IEnumerator senEnum = sentences.GetEnumerator();
			while (senEnum.MoveNext())
			{
				Sentence sen = (Sentence) senEnum.Current;

				writer.WriteStartElement(Grammar.Sentence.SentenceElement);
				writer.WriteElementString(Grammar.Sentence.NumberElement, sen.Number.ToString());
				writer.WriteElementString(Grammar.Sentence.PlaceElement, sen.Place.ToString());

				if (sen.ConnectingWord != null)
				{
					writer.WriteElementString(Grammar.Sentence.ConnectingWordElement, sen.ConnectingWord);
				}
				if (sen.NextId >= 0) writer.WriteElementString(Grammar.Sentence.NextIdElement, sen.NextId.ToString());

				writer.WriteEndElement();
			}
		}
	}
}
